package com.example.exam.ExcelListener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.excel.read.listener.ReadListener;
import com.example.exam.entity.temp.TempFile;
import com.example.exam.entity.temp.TempTeacher;
import com.example.exam.service.admin.AdminService;
import com.example.exam.service.temp.TempFileService;
import com.example.exam.utils.AmazeS3Utils;
import com.example.exam.utils.JsonUtils;
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author zhang
 */
@Data
@Log4j2
@Component
public class AddTeacherListener implements ReadListener<TempTeacher> {
    @Autowired
    private AmazeS3Utils amazeS3Utils;
    @Autowired
    private TempFileService tempFileService;

    private List<TempTeacher> tempTeacherList;
    JsonUtils<TempTeacher> jsonUtils;
    private AdminService adminService;
    private Integer BATCH_COUNT = 10;
    private List<String> tableName = new ArrayList<>();
    private List<TempTeacher> failUser = new ArrayList<>();

    @Autowired
    public AddTeacherListener(AdminService adminService) {
        this.adminService = adminService;
        this.tempTeacherList = new ArrayList<>(BATCH_COUNT);
        this.jsonUtils = new JsonUtils<>();
        tableName.add("name");
        tableName.add("sex");
        tableName.add("age");
        tableName.add("idcard");
    }

    @Override
    public void onException(Exception e, AnalysisContext analysisContext) throws Exception {
        throw e;
    }

    @Override
    public void invokeHead(Map<Integer, CellData> map, AnalysisContext analysisContext) {
        map.forEach((k, v) -> {
            int i = tableName.indexOf(v.getStringValue());
            log.info("i{}", i);
            log.info("head:{}", v);
            if (i != -1) {
                tableName.remove(v.getStringValue());
            }
        });
        if (!tableName.isEmpty()) {
            throw new RuntimeException("数据源不包含必要字段");
        }
    }

    @Override
    public void invoke(TempTeacher tempTeacher, AnalysisContext analysisContext) {
        log.info("解析到一条数据:{}", jsonUtils.t2String(tempTeacher));
        tempTeacherList.add(tempTeacher);
        if (tempTeacherList.size() >= BATCH_COUNT) {
            save();
            tempTeacherList.clear();
        }

    }

    @Override
    public void extra(CellExtra cellExtra, AnalysisContext analysisContext) {

    }


    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        save();
        log.info("数据解析完成");
        if (!failUser.isEmpty()) {
            byte[] s = Objects.requireNonNull(JsonUtils.o2s(failUser)).getBytes();
            String fileName = LocalDateTime.now() + "failUser.json";
            InputStream inputStream = new ByteArrayInputStream(s);
            amazeS3Utils.streamUpload(fileName, inputStream);
            tempFileService.save(new TempFile(TempFile.ADD_USER_ERROR, fileName));
            throw new RuntimeException("添加失败的人员");
        }
    }

    @Override
    public boolean hasNext(AnalysisContext analysisContext) {
        return false;
    }

    private void save() {
        failUser.addAll(adminService.saveAllTeacher(tempTeacherList));
        log.info("共有{}条待保存数据", tempTeacherList.size());
        log.info("保存成功");
    }
}
